package pers.xiaojun.boot.module.system.service.dict;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import pers.xiaojun.boot.mybatis.core.convert.PageConvert;
import pers.xiaojun.boot.common.exception.BusinessException;
import pers.xiaojun.boot.common.util.CollectionUtils;
import pers.xiaojun.boot.module.system.controller.dict.vo.data.DictDataQueryReqVO;
import pers.xiaojun.boot.module.system.controller.dict.vo.data.DictDataSaveRespVO;
import pers.xiaojun.boot.module.system.dao.entity.dict.DictDataDO;
import pers.xiaojun.boot.module.system.dao.mapper.dict.DictDataMapper;
import pers.xiaojun.boot.mybatis.core.query.LambdaQueryWrapperX;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static pers.xiaojun.boot.module.system.constants.BusinessCodeConstants.DICT_DATA_EXISTS;
import static pers.xiaojun.boot.module.system.constants.BusinessCodeConstants.DICT_LABEL_EXISTS;

/**
 * 字典数据服务层实现
 *
 * @author xiaojun
 * @since 2025-10-23
 */
@Service
@RequiredArgsConstructor
public class DictDataServiceImpl extends ServiceImpl<DictDataMapper, DictDataDO> implements DictDataService {

    private final DictTypeService dictTypeService;

    @Override
    public DictDataDO saveDictData(DictDataSaveRespVO saveVO) {
        validateDictDataBasicInfo(null, saveVO.getLabel());

        // 校验字典类型是否存在
        dictTypeService.validateDictTypeExists(saveVO.getDictType());

        DictDataDO dictData = BeanUtil.toBean(saveVO, DictDataDO.class);
        this.baseMapper.insert(dictData);

        return dictData;
    }

    @Override
    public DictDataDO updateDictData(DictDataSaveRespVO updateVO) {
        // 字典类型无法更新，进行置空
        updateVO.setDictType(null);

        validateDictDataExists(updateVO.getId());
        validateDictDataBasicInfo(updateVO.getId(), updateVO.getLabel());

        DictDataDO dictData = BeanUtil.toBean(updateVO, DictDataDO.class);
        this.baseMapper.updateById(dictData);

        return dictData;
    }

    @Override
    public void removeDictDataById(Long dictTypeId) {
        validateDictDataExists(dictTypeId);

        this.baseMapper.deleteById(dictTypeId);
    }

    @Override
    public void removeDictDataByIds(List<Long> dictDataIds) {
        List<DictDataDO> dictDataList = this.baseMapper.selectByIds(dictDataIds);
        if (dictDataList.size() != dictDataIds.size()) {
            Set<Long> notFindIds = Sets.difference(
                    new HashSet<>(dictDataIds),
                    CollectionUtils.convertSet(dictDataList, DictDataDO::getId)
            );
            throw new BusinessException(DICT_DATA_EXISTS.getCode(), StrUtil.format("字典数据Id {} 不存在", notFindIds));
        }

        this.baseMapper.deleteByIds(dictDataIds);
    }

    @Override
    public void removeDictDataByDictType(String dictType) {
        this.baseMapper.deleteByDictType(dictType);
    }

    @Override
    public void removeDictDataByDictTypes(List<String> dictTypes) {
        this.baseMapper.deleteByDictTypes(dictTypes);
    }

    @Override
    public List<DictDataDO> listDictDatasByStatusAndDictType(Integer status, String dictType) {
        return this.baseMapper.selectList(new LambdaQueryWrapperX<DictDataDO>()
                .eqIfPresent(DictDataDO::getStatus, status)
                .eqIfPresent(DictDataDO::getDictType, dictType)
                .orderByAsc(DictDataDO::getDictType)
                .orderByAsc(DictDataDO::getStatus)
        );
    }

    @Override
    public Page<DictDataDO> listDictDatasPage(DictDataQueryReqVO queryVO) {
        return this.baseMapper.selectPage(PageConvert.INSTANCE.toPage(queryVO), new LambdaQueryWrapperX<DictDataDO>()
                .eqIfPresent(DictDataDO::getDictType, queryVO.getDictType())
                .likeIfPresent(DictDataDO::getLabel, queryVO.getLabel())
                .eqIfPresent(DictDataDO::getStatus, queryVO.getStatus())
                .orderByAsc(DictDataDO::getSort)
        );
    }

    /**
     * 校验字典数据基本信息
     *
     * @param id    字典Id
     * @param label 字典标签
     */
    private void validateDictDataBasicInfo(Long id, String label) {
        DictDataDO dictData = this.baseMapper.selectByLabel(label);
        if (dictData != null && !dictData.getId().equals(id)) {
            throw new BusinessException(DICT_LABEL_EXISTS);
        }
    }

    /**
     * 校验字典数据是否存在
     *
     * @param dictDataId 字典数据Id
     * @return 字典数据
     */
    private DictDataDO validateDictDataExists(Long dictDataId) {
        DictDataDO dictData = this.baseMapper.selectById(dictDataId);
        if (dictData == null) {
            throw new BusinessException(DICT_DATA_EXISTS);
        }
        return dictData;
    }

}
